package com.ruoyi.common.utils;

import com.alibaba.fastjson.JSONObject;
import org.springframework.http.*;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;

/**
 * HttpClient 工具类
 *
 * @Author hanwu
 * @Date 2021-04-21 16:30
 **/
public class HttpClientUtil {

    /**
     * 携带请求头GET请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @return 请求信息
     */
    public static <T> T doGetWithHeader(String url, Map<String, String> headers, Class<T> clazz) {
        return doGet(url, headers, new HashMap<>(), clazz);
    }

    /**
     * 携带请求头和参数GET请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @param params  请求参数Map
     * @return 请求信息
     */
    public static <T> T doGetWithHeader(String url, Map<String, String> headers, Map<String, String> params, Class<T> clazz) {
        return doGet(url, headers, params, clazz);


    }

    /**
     * GET请求
     *
     * @param url 请求地址
     * @return 请求信息
     */
    public static <T> T doGet(String url, Class<T> clazz) {
        return doGet(url, new HashMap<>(), new HashMap<>(), clazz);

    }

    /**
     * 携带参数GET请求
     *
     * @param url    请求地址
     * @param params 请参数Map
     * @return 请求信息
     */
    public static <T> T doGet(String url, Map<String, String> params, Class<T> clazz) {
        return doGet(url, new HashMap<>(), params, clazz);

    }

    /**
     * GEt请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @param params  请求参数Map
     * @return 请求信息
     */
    private static <T> T doGet(String url, Map<String, String> headers, Map<String, String> params, Class<T> clazz) {
        if (!params.isEmpty()) {
            StringBuilder urlBuilder = new StringBuilder(url);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String name = entry.getKey();
                urlBuilder.append("?").append(name).append("={").append(name).append("}");
            }
            url = urlBuilder.toString();
        }
        // 设置请求头
        HttpHeaders header = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        header.setContentType(type);

        if (null != headers && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                header.add(entry.getKey(), entry.getValue());
            }
        }

        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<String> entity = new HttpEntity<>(null, header);

        ResponseEntity<T> responseEntity = null;

        try {
            responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, clazz, params);
        } catch (HttpClientErrorException e) {
            e.printStackTrace();
            throw new RemoteAccessException("get request error !");
        }
        if (responseEntity == null) {
            return null;
        }
        return responseEntity.getBody();

    }


    /**
     * 携带请求头POST请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @param param   请求参数
     * @return 请求信息
     */
    public static <T> T doPostWithHeader(String url, Map<String, String> headers, String param, Class<T> clazz) {
        return doPost(url, headers, param, clazz);
    }

    /**
     * POST请求
     *
     * @param url   请求地址
     * @param param 请求参数
     * @return 请求信息
     */
    public static <T> T doPost(String url, String param, Class<T> clazz) {
        return doPost(url, new HashMap<>(), param, clazz);
    }


    /**
     * POST请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @param param   请求参数
     * @return 请求信息
     */
    private static <T> T doPost(String url, Map<String, String> headers, String param, Class<T> clazz) {
        RestTemplate restTemplate = new RestTemplate();
        // 设置请求头
        HttpHeaders header = new HttpHeaders();
        // 设置请求类型为json
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        header.setContentType(type);
        if (null != headers && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                header.add(entry.getKey(), entry.getValue());
            }
        }
        HttpEntity<String> entity = new HttpEntity<>(param, header);
        ResponseEntity<T> responseEntity = null;
        try {
            responseEntity = restTemplate.postForEntity(url, entity, clazz);
        } catch (HttpClientErrorException e) {
            e.printStackTrace();
            throw new RemoteAccessException("post request error !");
        }
        if (responseEntity == null) {
            return null;
        }
        return responseEntity.getBody();

    }

    /**
     * 携带参数表单请求
     *
     * @param url    请求地址
     * @param params 请求参数Map
     * @return 请求信息
     */
    public static <T> T doPostForm(String url, MultiValueMap<String, String> params, Class<T> clazz) {
        return postForm(url, new HashMap<>(), params, clazz);
    }

    /**
     * 携带请求头和参数表单请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @param params  请求参数Map
     * @return 请求信息
     */
    public static <T> T doPostFormWithHeader(String url, Map<String, String> headers, MultiValueMap<String, String> params, Class<T> clazz) {
        return postForm(url, headers, params, clazz);

    }

    /**
     * 表单请求
     *
     * @param url     请求地址
     * @param headers 请求头Map
     * @param params  请求参数Map
     * @return 请求信息
     */
    private static <T> T postForm(String url, Map<String, String> headers, MultiValueMap<String, String> params, Class<T> clazz) {

        RestTemplate restTemplate = new RestTemplate();

        // 设置请求头为表单
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        if (null != headers && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                header.add(entry.getKey(), entry.getValue());
            }
        }

        // 构造请求体
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, header);

        ResponseEntity<T> response = null;
        try {
            response = restTemplate.postForEntity(url, request, clazz);
        } catch (HttpClientErrorException e) {
        }
        if (response == null) {
            return null;
        }
        return response.getBody();

    }


    /**
     * 绕过验证
     */
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("SSLv3");

        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sc.init(null, new TrustManager[]{trustManager}, null);
        return sc;
    }

}
